package com.hu.hutool.config;

import com.hu.hutool.common.CommonConstant;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.UUID;

/**
 * <p>mvc过滤器</p>
 *
 * @Author CazCen
 * @Date 2021/10/24 21:04
 */
@Component
public class WebMvcFilter implements Filter {

    /**
     * 设置响应头，响应头名字（惯例是大写）
     */
    private static final String REQUEST_ID_HEADER = CommonConstant.LOG_TRACE_ID;

    /**
     * 设置到 MDC 里的key（惯例使用小驼峰，为了统一这里也用大写）
     */
    private static final String LOG_TRACE_ID = CommonConstant.LOG_TRACE_ID;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {


        HttpServletRequest httpRequest = null;
        try {
            httpRequest = (HttpServletRequest) servletRequest;
            HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
            String traceId = httpRequest.getHeader(LOG_TRACE_ID);
            if (StringUtils.isEmpty(traceId)) {
                traceId = UUID.randomUUID().toString().replace("-", "").substring(0, 16);
            }
            //将traceId 设置为 mdc 中
            MDC.put(LOG_TRACE_ID, traceId);

            // 获取请求ip，并且设置到 mdc 中
            String ip = getRequestSourceIp(httpRequest);
            MDC.put("IP", ip);

            // 将 traceId 设置到 header 中
            // httpResponse.setHeader(LOG_TRACE_ID, traceId);

            // 将 IP 设置到 header 中
            // httpResponse.setHeader("IP", ip);

            filterChain.doFilter(httpRequest, httpResponse);

        } catch (Exception exception) {
            exception.printStackTrace();
            MDC.clear();
        }


    }

    @Override
    public void destroy() {

    }


    /**
     * 获取请求来源的IP,可以适应前置部署有Nginx等反向代理软件等的情况. HTTP_CLIENT_IP 无法伪造，所以放在第一个
     * http://blog.csdn.net/songylwq/article/details/7701718
     *
     * @param request : 请求对象
     * @return static
     */
    public static String getRequestSourceIp(HttpServletRequest request) {
        String ip = request.getHeader("HTTP_CLIENT_IP");

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_FORWARDED");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-FORWARDED-FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

}
